/**
 * 性能优化工具函数
 */

/**
 * 防抖函数 - 避免频繁调用
 * @param {Function} func 要防抖的函数
 * @param {number} delay 延迟时间(ms)
 * @param {boolean} immediate 是否立即执行
 * @returns {Function} 防抖后的函数
 */
export function debounce(func, delay = 300, immediate = false) {
  let timeoutId = null
  let result = null

  const debounced = function (...args) {
    const callNow = immediate && !timeoutId

    const later = () => {
      timeoutId = null
      if (!immediate) {
        result = func.apply(this, args)
      }
    }

    clearTimeout(timeoutId)
    timeoutId = setTimeout(later, delay)

    if (callNow) {
      result = func.apply(this, args)
    }

    return result
  }

  debounced.cancel = () => {
    clearTimeout(timeoutId)
    timeoutId = null
  }

  return debounced
}

/**
 * 节流函数 - 限制调用频率
 * @param {Function} func 要节流的函数
 * @param {number} delay 节流间隔(ms)
 * @returns {Function} 节流后的函数
 */
export function throttle(func, delay = 300) {
  let timeoutId = null
  let lastExec = 0

  return function (...args) {
    const elapsed = Date.now() - lastExec

    const exec = () => {
      lastExec = Date.now()
      func.apply(this, args)
    }

    clearTimeout(timeoutId)

    if (elapsed > delay) {
      exec()
    } else {
      timeoutId = setTimeout(exec, delay - elapsed)
    }
  }
}

/**
 * 懒加载组件 - 优化初始渲染
 * @param {Function} importFunc 动态导入函数
 * @param {Object} options 配置选项
 * @returns {Object} Vue异步组件配置
 */
export function lazyComponent(importFunc, options = {}) {
  const {
    loading: LoadingComponent,
    error: ErrorComponent,
    delay = 200,
    timeout = 60000
  } = options

  return {
    component: importFunc,
    loading: LoadingComponent,
    error: ErrorComponent,
    delay,
    timeout
  }
}

/**
 * 虚拟滚动Hook - 优化大数据渲染
 * @param {Object} options 配置选项
 * @returns {Object} 虚拟滚动相关状态和方法
 */
export function useVirtualScroll(options = {}) {
  const {
    itemHeight = 50,
    containerHeight = 400,
    buffer = 5
  } = options

  const startIndex = ref(0)
  const endIndex = ref(0)
  const scrollTop = ref(0)
  const containerRef = ref(null)

  const visibleCount = computed(() => Math.ceil(containerHeight / itemHeight))

  const updateRange = (scrollTopValue, totalCount) => {
    const newStartIndex = Math.floor(scrollTopValue / itemHeight)
    const newEndIndex = Math.min(
      newStartIndex + visibleCount.value + buffer * 2,
      totalCount
    )

    startIndex.value = Math.max(0, newStartIndex - buffer)
    endIndex.value = newEndIndex
  }

  const handleScroll = throttle((event) => {
    scrollTop.value = event.target.scrollTop
  }, 16) // 60fps

  return {
    startIndex,
    endIndex,
    scrollTop,
    containerRef,
    visibleCount,
    updateRange,
    handleScroll
  }
}

/**
 * 批量操作Hook - 优化批量更新
 * @param {Function} batchFn 批量处理函数
 * @param {number} delay 批量延迟时间
 * @returns {Object} 批量操作相关方法
 */
export function useBatchOperation(batchFn, delay = 100) {
  const pendingItems = ref([])
  const isProcessing = ref(false)
  let timeoutId = null

  const addToBatch = (item) => {
    pendingItems.value.push(item)

    clearTimeout(timeoutId)
    timeoutId = setTimeout(processBatch, delay)
  }

  const processBatch = async () => {
    if (pendingItems.value.length === 0 || isProcessing.value) return

    isProcessing.value = true
    const items = [...pendingItems.value]
    pendingItems.value = []

    try {
      await batchFn(items)
    } catch (error) {
      console.error('Batch operation failed:', error)
    } finally {
      isProcessing.value = false
    }
  }

  return {
    addToBatch,
    processBatch,
    isProcessing,
    pendingCount: computed(() => pendingItems.value.length)
  }
}

/**
 * 内存清理Hook - 防止内存泄漏
 * @returns {Object} 清理相关方法
 */
export function useCleanup() {
  const timers = []
  const observers = []
  const subscriptions = []

  const addTimer = (timer) => {
    timers.push(timer)
    return timer
  }

  const addObserver = (observer) => {
    observers.push(observer)
    return observer
  }

  const addSubscription = (subscription) => {
    subscriptions.push(subscription)
    return subscription
  }

  const cleanup = () => {
    // 清理定时器
    timers.forEach(timer => {
      if (typeof timer === 'number') {
        clearTimeout(timer)
        clearInterval(timer)
      }
    })

    // 清理观察者
    observers.forEach(observer => {
      if (observer && typeof observer.disconnect === 'function') {
        observer.disconnect()
      }
    })

    // 清理订阅
    subscriptions.forEach(subscription => {
      if (subscription && typeof subscription.unsubscribe === 'function') {
        subscription.unsubscribe()
      }
    })

    // 清空数组
    timers.length = 0
    observers.length = 0
    subscriptions.length = 0
  }

  // 组件卸载时自动清理
  onUnmounted(cleanup)

  return {
    addTimer,
    addObserver,
    addSubscription,
    cleanup
  }
}

/**
 * 智能缓存Hook - 优化数据缓存
 * @param {number} maxSize 最大缓存大小
 * @param {number} ttl 缓存生存时间(ms)
 * @returns {Object} 缓存相关方法
 */
export function useSmartCache(maxSize = 100, ttl = 5 * 60 * 1000) {
  const cache = new Map()
  const timestamps = new Map()

  const get = (key) => {
    const now = Date.now()
    const timestamp = timestamps.get(key)

    if (!timestamp || now - timestamp > ttl) {
      cache.delete(key)
      timestamps.delete(key)
      return null
    }

    return cache.get(key)
  }

  const set = (key, value) => {
    const now = Date.now()

    // 如果缓存已满，删除最旧的条目
    if (cache.size >= maxSize) {
      const oldestKey = [...timestamps.entries()]
        .sort(([,a], [,b]) => a - b)[0][0]
      cache.delete(oldestKey)
      timestamps.delete(oldestKey)
    }

    cache.set(key, value)
    timestamps.set(key, now)
  }

  const has = (key) => {
    const now = Date.now()
    const timestamp = timestamps.get(key)
    return timestamp && now - timestamp <= ttl
  }

  const clear = () => {
    cache.clear()
    timestamps.clear()
  }

  // 定期清理过期缓存
  const cleanupInterval = setInterval(() => {
    const now = Date.now()
    for (const [key, timestamp] of timestamps.entries()) {
      if (now - timestamp > ttl) {
        cache.delete(key)
        timestamps.delete(key)
      }
    }
  }, ttl)

  onUnmounted(() => {
    clearInterval(cleanupInterval)
    clear()
  })

  return {
    get,
    set,
    has,
    clear,
    size: computed(() => cache.size)
  }
}
